package com.ibeeking.found.cop.b.rest.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ibeeking.found.common.utils.UserUtils;
import com.ibeeking.found.cop.b.rest.service.IGroupTagsClassService;
import com.ibeeking.found.cop.b.rest.service.IGroupTagsService;
import com.ibeeking.found.cop.service.common.dos.GroupTagsClassDO;
import com.ibeeking.found.cop.service.common.dos.GroupTagsDO;
import com.ibeeking.found.cop.service.common.param.GroupTagsClassParam;
import com.ibeeking.found.cop.service.common.param.GroupTagsParam;
import com.ibeeking.found.cop.service.common.query.GroupTagsClassPageQuery;
import com.ibeeking.found.cop.service.common.query.GroupTagsClassQuery;
import com.ibeeking.found.cop.service.common.vo.GroupTagsClassVO;
import com.ibeeking.found.cop.service.common.vo.GroupTagsVO;
import com.ibeeking.found.cop.service.mapper.GroupTagsClassMapper;
import com.ibeeking.found.cop.service.mapper.GroupTagsMapper;
import com.ibeeking.found.id.GenerateId;
import com.ibeeking.nematos.exception.BusinessException;
import com.ibeeking.nematos.utils.bean.BeanUtil;
import com.ibeeking.nematos.utils.data.Collections3;
import com.ibeeking.nematos.utils.id.IdGenerator;
import com.ibeeking.nematos.utils.json.JsonUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @ClassName GroupTagsClassServiceImpl
 * @Description
 * @Author ibeeking
 * @Date 2021-01-27 18:50
 **/
@Service
public class GroupTagsClassServiceImpl extends ServiceImpl<GroupTagsClassMapper, GroupTagsClassDO> implements IGroupTagsClassService {

    @Resource
    private GroupTagsClassMapper groupTagsClassMapper;

    @Resource
    private GroupTagsMapper groupTagsMapper;

    @Resource
    private IGroupTagsService groupTagsServiceImpl;

    @Override
    public List<GroupTagsClassVO> list(GroupTagsClassQuery query) {
        List<GroupTagsClassDO> entityDOS = groupTagsClassMapper.selectList(new LambdaQueryWrapper<GroupTagsClassDO>()
                .eq(query.getId() != null, GroupTagsClassDO::getId, query.getId())
                .eq(StringUtils.isNotBlank(query.getClassCode()), GroupTagsClassDO::getClassCode, query.getClassCode())
                .like(StringUtils.isNotBlank(query.getClassName()), GroupTagsClassDO::getClassName, query.getClassName())
                .orderByDesc(GroupTagsClassDO::getCreateTime)
        );
        List<GroupTagsClassVO> entityVOS =JsonUtils.jsonToList(entityDOS, GroupTagsClassVO.class);
        if(Collections3.isNotEmpty(entityVOS)){
            entityVOS.stream().forEach(d->{
               Long groupId = d.getId();
               List<GroupTagsDO> tagsListDOS = groupTagsMapper.selectList(new LambdaQueryWrapper<GroupTagsDO>().eq(GroupTagsDO::getClassId,groupId));
               if(Collections3.isNotEmpty(tagsListDOS)) {
                   List<GroupTagsVO> tagsListVOS = JsonUtils.jsonToList(tagsListDOS, GroupTagsVO.class);
                   d.setTagsList(tagsListVOS);
               }
            });
        }
        return entityVOS;
    }

    @Override
    public Page<GroupTagsClassVO> pageList(GroupTagsClassPageQuery pageQuery) {
        LambdaQueryWrapper<GroupTagsClassDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(pageQuery.getId() != null, GroupTagsClassDO::getId, pageQuery.getId())
                .eq(StringUtils.isNotBlank(pageQuery.getClassCode()), GroupTagsClassDO::getClassCode, pageQuery.getClassCode())
                .like(StringUtils.isNotBlank(pageQuery.getClassName()), GroupTagsClassDO::getClassName, pageQuery.getClassName())
                .orderByDesc(GroupTagsClassDO::getCreateTime);
        Page<GroupTagsClassDO> entityDOPages = groupTagsClassMapper.selectPage(new Page<GroupTagsClassDO>(pageQuery.getPageNum(), pageQuery.getPageSize()), wrapper);
        Page<GroupTagsClassVO> entityVOPages = BeanUtil.convertPage(entityDOPages, GroupTagsClassVO.class);
        if(entityVOPages!=null && entityVOPages.getSize()>0){
            List<GroupTagsClassVO> GroupTagsClassVOS = entityVOPages.getRecords();
            if(Collections3.isNotEmpty(GroupTagsClassVOS)){
                GroupTagsClassVOS.stream().forEach(d->{
                    Long groupId = d.getId();
                    List<GroupTagsDO> tagsListDOS = groupTagsMapper.selectList(new LambdaQueryWrapper<GroupTagsDO>().eq(GroupTagsDO::getClassId,groupId));
                    if(Collections3.isNotEmpty(tagsListDOS)) {
                        List<GroupTagsVO> tagsListVOS = JsonUtils.jsonToList(tagsListDOS, GroupTagsVO.class);
                        d.setTagsList(tagsListVOS);
                    }
                });
                entityVOPages.setRecords(GroupTagsClassVOS);
            }
        }

        return entityVOPages;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean add(GroupTagsClassParam param) {
        GroupTagsClassDO groupEntityDO = BeanUtil.convertBean(param, GroupTagsClassDO.class);
        Long groupId = GenerateId.generateId();
        groupEntityDO.setId(groupId);
        groupEntityDO.setSort(groupId);
        groupEntityDO.setCreateBy(UserUtils.getUserId());
        groupEntityDO.setCreateTime(LocalDateTime.now());
        groupEntityDO.setModifyTime(LocalDateTime.now());
        List<GroupTagsParam> GroupTagsParamList = param.getTagsList();
        if(Collections3.isNotEmpty(GroupTagsParamList)){
            List<GroupTagsDO> GroupTagsDOS = new ArrayList<>();
            for(GroupTagsParam entityParam: GroupTagsParamList) {
                GroupTagsDO tagsEntityDO = BeanUtil.convertBean(entityParam, GroupTagsDO.class);
                Long tagsId = GenerateId.generateId();
                tagsEntityDO.setId(tagsId);
                tagsEntityDO.setClassId(groupId);
                tagsEntityDO.setCreateBy(UserUtils.getUserId());
                tagsEntityDO.setCreateTime(LocalDateTime.now());
                tagsEntityDO.setModifyTime(LocalDateTime.now());
                tagsEntityDO.setSort(entityParam.getSort());
                tagsEntityDO.setType(0);
                tagsEntityDO.setStatus(0);
                tagsEntityDO.setDelStatus(0);
                GroupTagsDOS.add(tagsEntityDO);
            }

            if(Collections3.isNotEmpty(GroupTagsDOS)) {
                groupTagsMapper.insertBatchSomeColumn(GroupTagsDOS);
            }
        }

        return groupTagsClassMapper.insert(groupEntityDO) > 0;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean modify(GroupTagsClassParam param) {
        if(param != null ) {
            Long groupId= param.getId();
            List<Long> allNeedDeletedTags = new ArrayList<>();
            List<GroupTagsDO> allNeedInsertTags = new ArrayList<>();
            List<GroupTagsDO> allNeedUpdateTags = new ArrayList<>();

            List<GroupTagsParam> newTagsList = param.getTagsList();

            GroupTagsClassDO entityDO = BeanUtil.convertBean(param, GroupTagsClassDO.class);
            entityDO.setModifyBy(UserUtils.getUserId());
            entityDO.setModifyTime(LocalDateTime.now());
            List<GroupTagsDO> oldAllTagsList = groupTagsMapper.selectList(new LambdaQueryWrapper<GroupTagsDO>().eq(GroupTagsDO::getClassId, groupId));
            Map<Long, GroupTagsDO> oldAllTagsMap = Collections3.isNotEmpty(oldAllTagsList)?oldAllTagsList.parallelStream().collect(Collectors.toMap(GroupTagsDO::getId, x->x, (o, n) -> o)):null;
            List<Long> allOldTagsIdList =  Collections3.isNotEmpty(oldAllTagsList)?oldAllTagsList.stream().map(GroupTagsDO::getId).collect(Collectors.toList()):null;
            List<Long> allNewTagsIdList = Collections3.isNotEmpty(newTagsList)?newTagsList.stream().map(GroupTagsParam::getId).collect(Collectors.toList()):null;
            if(Collections3.isNotEmpty(allOldTagsIdList) && Collections3.isNotEmpty(allNewTagsIdList)){
                HashSet<Long> allOldTagsIdHash = new HashSet<>(allOldTagsIdList);
                HashSet<Long> allNewTagsIdHsh = new HashSet<>(allNewTagsIdList);
                if(allOldTagsIdHash.removeAll(allNewTagsIdHsh)){
                    allNeedDeletedTags = new ArrayList<>(allOldTagsIdHash);
                }
            }
            if (Collections3.isNotEmpty(newTagsList)) {
                for (GroupTagsParam entityParam : newTagsList) {
                    Long tagsId = entityParam.getId();
                    if(tagsId !=null && oldAllTagsMap.containsKey(tagsId)) {
                        GroupTagsDO tagsEntityDO = BeanUtil.convertBean(entityParam, GroupTagsDO.class);
                        tagsEntityDO.setClassId(groupId);
                        tagsEntityDO.setModifyBy(UserUtils.getUserId());
                        tagsEntityDO.setModifyTime(LocalDateTime.now());
                        tagsEntityDO.setSort(entityParam.getSort());
                        tagsEntityDO.setType(0);
                        tagsEntityDO.setStatus(0);
                        tagsEntityDO.setDelStatus(0);
                        allNeedUpdateTags.add(tagsEntityDO);
                    }else{
                        GroupTagsDO tagsEntityDO = new GroupTagsDO();
                        tagsEntityDO.setId(IdGenerator.getId());
                        tagsEntityDO.setClassId(groupId);
                        tagsEntityDO.setTagsName(entityParam.getTagsName());
                        tagsEntityDO.setSort(entityParam.getSort());
                        tagsEntityDO.setCreateBy(UserUtils.getUserId());
                        tagsEntityDO.setCreateTime(LocalDateTime.now());
                        tagsEntityDO.setModifyTime(LocalDateTime.now());
                        tagsEntityDO.setSort(entityParam.getSort());
                        tagsEntityDO.setType(0);
                        tagsEntityDO.setStatus(0);
                        tagsEntityDO.setDelStatus(0);
                        allNeedInsertTags.add(tagsEntityDO);
                    }
                }
            }

            if(Collections3.isNotEmpty(allNeedDeletedTags)){
                groupTagsMapper.delete(new LambdaQueryWrapper<GroupTagsDO>().in(GroupTagsDO::getId, allNeedDeletedTags));
            }

            if(Collections3.isNotEmpty(allNeedInsertTags)){
                groupTagsMapper.insertBatchSomeColumn(allNeedInsertTags);
            }

            if(Collections3.isNotEmpty(allNeedUpdateTags)){
                groupTagsServiceImpl.updateBatch(allNeedUpdateTags);
            }

            return groupTagsClassMapper.updateById(entityDO) > 0;
        }else{
            return false;
        }
    }

    @Override
    public GroupTagsClassVO view(Long id) {
        GroupTagsClassDO entityDO = groupTagsClassMapper.selectById(id);
        if(entityDO == null) throw new BusinessException("没有查到相关记录！");
        GroupTagsClassVO entityVO = BeanUtil.convertBean(entityDO, GroupTagsClassVO.class);
        if(entityVO!=null){
            Long groupId = entityVO.getId();
            List<GroupTagsDO> tagsListDOS = groupTagsMapper.selectList(new LambdaQueryWrapper<GroupTagsDO>().eq(GroupTagsDO::getClassId,groupId));
            if(Collections3.isNotEmpty(tagsListDOS)) {
                List<GroupTagsVO> tagsListVOS = JsonUtils.jsonToList(tagsListDOS, GroupTagsVO.class);
                entityVO.setTagsList(tagsListVOS);
            }
        }
        return entityVO;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean changeStatus(Long id, Integer status) {
        GroupTagsClassDO groupDO = groupTagsClassMapper.selectById(id);
        if(groupDO==null) throw new BusinessException("没有查到相关记录!");
        List<GroupTagsDO> entityDOS = groupTagsMapper.selectList(new LambdaQueryWrapper<GroupTagsDO>().eq(GroupTagsDO::getClassId, id));
        if(Collections3.isEmpty(entityDOS)) throw new BusinessException("没有查到相关记录！");
        entityDOS.parallelStream().forEach(d->{
            d.setStatus(status);
            d.setModifyBy(UserUtils.getUserId());
            d.setModifyTime(LocalDateTime.now());
        });
        groupTagsServiceImpl.updateBatch(entityDOS);
        groupDO.setStatus(status);
        groupDO.setModifyBy(UserUtils.getUserId());
        groupDO.setModifyTime(LocalDateTime.now());
        return groupTagsClassMapper.updateById(groupDO) >0;
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean del(Long id) {
        GroupTagsClassDO entityDO = groupTagsClassMapper.selectById(id);
        if(entityDO == null) throw new BusinessException("没有查到相关记录！");
        groupTagsMapper.delete(new LambdaQueryWrapper<GroupTagsDO>().eq(GroupTagsDO::getClassId, id));
        return groupTagsClassMapper.deleteById(id) > 0;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean updateBatchById(List<GroupTagsClassDO> entityList){
       Boolean reulst = updateBatchById(entityList);
       return reulst;
    }

}
